﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Common
{
    public class Url
    {
        private static String sUnsafeString = "\"<>%\\^[]`+$,@:;/!#?=& ";

        private static String Convert(string val)
        {
            byte[] values = Encoding.UTF8.GetBytes(val);

            string result = "";

            foreach (byte b in values)
                result += "%" + b.ToString("X2");

            return result;
        }

        private static string Revert(string val)
        {
            if (0 != val.Length % 3) return val;
 
            byte[] currentValue = new byte[val.Length / 3];

            for (int i = 1; i < val.Length; ++i)
            {
                currentValue[i / 3] *= 16;

                if (val[i] >= 'A' && val[i] <= 'F')
                    currentValue[i / 3] += (byte)((byte)(val[i] - 'A') + 10);
                else if (val[i] >= 'a' && val[i] <= 'f')
                    currentValue[i / 3] += (byte)((byte)(val[i] - 'a') + 10);
                else
                    currentValue[i / 3] += (byte)(val[i] - '0');
            }

            return Encoding.UTF8.GetString(currentValue, 0, currentValue.Length);
        }

        private static bool isUnsafe(char compareChar)
        {
            bool bcharfound = (sUnsafeString.IndexOf(compareChar) >= 0);
            int char_ascii_value = (int)compareChar;

            if (!bcharfound && char_ascii_value > 32 && char_ascii_value < 123)
                return false;

            return true;
        }

        public static string UrlEncode(string sEncode)
        {
            string sEncoded = "";

            foreach (char ch in sEncode)
            {
                if (!isUnsafe(ch))
                    sEncoded += ch.ToString();
                else
                    sEncoded += Convert(ch.ToString());
            }

            return sEncoded;
        }

        public static string UrlDecode(string sEncoded)
        {
            string sTmp = sEncoded;
            string sResult = "";

            int index = sTmp.IndexOf('%');

            while (index >= 0)
            {
                sResult += sTmp.Substring(0, index);
                sTmp = sTmp.Substring(index);
                index = sTmp.IndexOf('%');

                int cnt = 1;

                while (index + cnt * 3 <= sTmp.Length && sTmp.IndexOf('%', index + cnt * 3) == index + cnt * 3) ++cnt;

                if (index + cnt * 3 <= sTmp.Length)
                {
                    sResult += Revert(sTmp.Substring(index, cnt * 3));
                    sTmp = sTmp.Substring(index + cnt * 3);

                    index = sTmp.IndexOf('%');
                }
                else
                    index = -1;
            }

            sResult += sTmp;

            return sResult;
        }
    }
}
